package org.example.handwriting.spring;

import org.example.handwriting.spring.Annotation.Autowired;
import org.example.handwriting.spring.Annotation.Component;
import org.example.handwriting.spring.Annotation.PostConstruct;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class BeanDefinition {

    /**
     * bean名字
     */
    private String name;

    /**
     * bean 构造函数
     */
    private Constructor<?> constructor;

    /**
     * 含有PostConstruct注解的方法
     */
    private ArrayList<Method> methodArrayList;

    /**
     * 需要Autowired注解的字段
     */
    private ArrayList<Field> fieldArrayList;

    private Class<?> beanType;

    public BeanDefinition(Class<?> type) {
        Component component = type.getDeclaredAnnotation(Component.class);
        this.beanType = type;
        if (component.name().isEmpty()) {
            // getSimpleName() 返回 类的简单名称不包含包名 如 java.util.ArrayList，则返回 "ArrayList"
            // getName() 返回 类的全限定名称包括包名 如 java.util.ArrayList，则返回 "java.util.ArrayList"
            this.name = type.getSimpleName();
        } else {
            this.name = component.name();
        }
        try {
            this.constructor = type.getConstructor();
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

        this.fieldArrayList = getArrayListMethodByAutowired(type.getDeclaredFields());
        this.methodArrayList = getArrayListMethodByPostConstruct(type.getDeclaredMethods());
    }

    /**
     * 获取含有Autowired注解的字段
     */
    private ArrayList<Field> getArrayListMethodByAutowired(Field[] fields) {
        ArrayList<Field> res = new ArrayList<>();
        for (Field field : fields) {
            if (field.isAnnotationPresent(Autowired.class)) {
                res.add(field);
            }
        }
        return res;
    }

    /**
     * 获取含有PostConstruct注解的方法
     */
    private ArrayList<Method> getArrayListMethodByPostConstruct(Method[] methods) {
        ArrayList<Method> res = new ArrayList<>();

        for (Method method : methods) {
            // 该方法是否含有PostConstruct 注解
            if (method.isAnnotationPresent(PostConstruct.class)) {
                res.add(method);
            }
        }

        return res;
    }

    public String getName() {
        return this.name;
    }

    public Constructor<?> getConstructor() {
        return this.constructor;
    }

    public ArrayList<Method> getMethodArrayList() {
        return methodArrayList;
    }

    public ArrayList<Field> getFieldArrayList() {
        return fieldArrayList;
    }

    public Class<?> getBeanType() {
        return beanType;
    }
}
